package n3_临界区critical_zone;


import lombok.extern.slf4j.Slf4j;

/**
 * ----------------------------------------------------
 *                                                    /
 *      ----- synchronized 解决 竞态条件 ------         /
 *                                                    /
 * ====================================================
 *
 * synchronized 即俗称的【对象锁】
 *
 * 它采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】，
 *
 * 其它线程再想获取这个【对象锁】时就会阻塞住。
 *
 * 保证拥有锁的线程可以<b>安全的执行临界区内的代码<b/>，不用担心线程上下文切换
 *
 * 用【对象锁】保证了[临界区内代码]的<b>原子性</b>>，[临界区内的代码]对外是不可分割的，不会被线程切换所打断。
 *
 * ------------------------------------------------
 * 锁住的是 JVM 里 四行代码 【如果 synchronized放在for循环外面 那么锁住的是 4 * 5000 = 20000行代码 原子的整体，20000行代码执行期间不会被其他线程干扰】
 * getstatic i    // 获取静态变量i的值
 * iconst_1       // 准备常量1
 * iadd           // 自增
 * putstatic i    // 将修改后的值存入静态变量i
 * ================================================
 */
@Slf4j(topic = "c.T2_临界区_加锁synchronized")
public class T2_临界区_加锁synchronized {

    static int counter = 0;
    static final Object room = new Object();

    public static void main(String[] args) throws InterruptedException {
        log.debug("----- begin -----");
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {

                synchronized (room){ // 放在 for循环外面 将 锁住  4 * 5000 = 20000行代码 原子的整体
                    log.debug("++++++"+i);
                    counter++;
                }

            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {

                synchronized (room){  // 放在 for循环外面 将 锁住  4 * 5000 = 20000行代码 原子的整体
                    log.debug("------"+i);
                    counter--;
                }

            }
        }, "t2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.debug("----- end 最终结果是：{} -----",counter);
    }



}
